package treeedit;

import java.util.*;
import java.io.*;

public class Lisper {
	private static Lisper instance;
	private Properties props = new Properties();
	private Properties userFuns = new Properties();
	
	class LispFun {
		String name;
		public LispFun(String name) {
			this.name = name;
		}
	}

	public static Lisper getInstance() {
		if(instance==null)
			return (instance = new Lisper());
		return instance;
	}
	private Lisper() {
		try {
			InputStream input = Configuration.class.getResourceAsStream("lispDoc.xml");
			props.loadFromXML(input);
		} catch (Exception e) { 
			System.err.println("Lisp documentation not found");
		}
	}
	public CodeDictionary getDictionary() {
		Set dictSet = new HashSet();
		dictSet.addAll(props.keySet());
		dictSet.addAll(userFuns.keySet());
		return new CodeDictionary(dictSet);
	}
	public boolean isFunction(String name) {
		if (name.equals("")) return false;
		return ( 
				!(props.getProperty(name.toLowerCase())==null) || // true if lisp function 
				!(userFuns.getProperty(name.toLowerCase())==null));  // true if user function
	}

	public String getDescription(String function) {
		String ret = "";
		if((ret= props.getProperty(function))!=null)
			return ret;
		if((ret= userFuns.getProperty(function))!=null)
			return ret;
		return "";
	}
	private Set<String> searchDefuns(CodeNode root) {
		Set<String> ret = new HashSet<String>();
		for(CodeNode node : root.getChildren()) {
			
			if(node.getChildren().size()>1 
					&& node.getChildren().get(0).getCode().equals("defun")  // found defun
					&& !node.getChildren().get(1).getCode().equals("( )")) { // first argument to defun is an atom (fun name)
				ret.add(node.getChildren().get(1).getCode().toLowerCase());
			} else if (node.getChildren().size() > 0) {
				ret.addAll(searchDefuns(node));
			}
		}
		return ret;
	}

	public void checkDefuns(CodeNode root) {
		Set<String> fresh = searchDefuns(root);
		Properties newUserFuns = new Properties(userFuns);
		// usuwamy usuniete
		for(Object defun : userFuns.keySet()) {
			String name = (String)defun;
			if(!fresh.contains(name.toLowerCase())) {
				//props.remove(name);
				newUserFuns.remove(name);
			}
		}
		userFuns = newUserFuns;
		// dodajemy dodane
		for(String defun : fresh) {
			if(userFuns.get(defun)==null) {
				userFuns.setProperty(defun,"[user function]");
				//props.setProperty(defun,"[user function]");
			}
		}
//		System.out.println("CN: fresh defs: " + fresh);
		
	}
}

